#ifndef NSREFDATATOOL_REF_SHEET_H_
#define NSREFDATATOOL_REF_SHEET_H_

class CNSRefDataToolDoc;
class RefSheet
{
public:
	static const wchar_t Expression_Description = '#';
	static const wchar_t Expression_PrimaryKey = '!';
	static const wchar_t Expression_NoDBPatch = '~';

	class Column
	{
	public:
		class Data
		{
		public:
			Data(const wchar_t* value) : value_(value) {}
			~Data() {}

			void set_value(const wchar_t* value) { value_ = value; }
			const wchar_t* value() const { return value_.c_str(); }
			
		private:
			std::wstring value_;
		};
		typedef std::vector<Data*> VECTOR_DATAS;

		Column() : db_patch_(true) {}
		Column(const wchar_t* name, bool db_patch = true) : name_(name), db_patch_(db_patch) {}
		~Column()
		{
			VECTOR_DATAS::iterator data_end = datas_.end();
			for (VECTOR_DATAS::iterator data_iter = datas_.begin(); data_iter != data_end; ++data_iter)
			{
				delete (*data_iter);
			}
		}

		Data* FindData(const wchar_t* value)
		{
			VECTOR_DATAS::iterator data_end = datas_.end();
			for (VECTOR_DATAS::iterator data_iter = datas_.begin(); data_iter != data_end; ++data_iter)
			{
				if (lstrcmp((*data_iter)->value(), value) == 0)
					return (*data_iter);
			}

			return NULL;
		}

		const wchar_t* name() const { return name_.c_str(); }
		void set_name(const wchar_t* name) { name_ = name; }
		void set_data(Data* data) { datas_.push_back(data); }
		const VECTOR_DATAS& datas() const { return datas_; }
		Data* data(unsigned long row) const { return datas_[row]; }
		bool db_patch() const { return db_patch_; }
		
	private:
		std::wstring name_;
		VECTOR_DATAS datas_;
		bool db_patch_;
	};
	typedef std::list<Column*> LIST_COLUMNS;
	typedef std::map<std::wstring, Column::Data*> MAP_PK_DATAS;

	RefSheet(const wchar_t* name, bool db_patch = true) : name_(name), row_count_(0), db_patch_(db_patch), selected_(false) {}
	~RefSheet();

	bool Init(ExcelLibrary::ISheet* sheet, CNSRefDataToolDoc* doc);
	
	Column* FindColumn(const wchar_t* name)
	{
		LIST_COLUMNS::iterator column_end = columns_.end();
		for (LIST_COLUMNS::iterator column_iter = columns_.begin(); column_iter != column_end; ++column_iter)
		{
			if (lstrcmp((*column_iter)->name(), name) == 0)
			{
				return (*column_iter);
			}
		}

		return NULL;
	}

	Column::Data* FindPKData(const wchar_t* pk)
	{
		MAP_PK_DATAS::iterator find_iter = pk_datas_.find(pk);
		if (find_iter != pk_datas_.end())
		{
			return (*find_iter).second;
		}

		return NULL;		
	}

	void DisableDBPatch() { db_patch_ = false; }

	const wchar_t* name() const { return name_.c_str(); }
	const LIST_COLUMNS columns() const { return columns_; }
	unsigned long row_count() const { return row_count_; }
	bool db_patch() const { return db_patch_; }
	bool selected() const { return selected_; }
	void set_selected(bool selected) { selected_ = selected; }
	
private:
	void Reset();

	std::wstring name_;
	LIST_COLUMNS columns_;
	MAP_PK_DATAS pk_datas_;
	unsigned long row_count_;
	bool db_patch_;
	bool selected_;
};

#endif // NSREFDATATOOL_REF_SHEET_H_